package org.example.base;

import cn.hutool.core.text.CharSequenceUtil;
import cn.hutool.core.util.DesensitizedUtil;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.BeanProperty;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.databind.ser.ContextualSerializer;
import lombok.extern.slf4j.Slf4j;
import org.example.annotation.Desensitization;
import org.example.config.DesensitizationAutoConfiguration;

import java.io.IOException;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

@Slf4j
public class DesensitizationSerialize extends JsonSerializer<String> implements ContextualSerializer {

    private Integer startInclude;

    private Integer endExclude;

    private DesensitizationTypeEnum type;

    private static boolean enabled;

    /**
     * 设置开关
     *
     * @param enabledFlag true：开   false：关
     */
    public static void setEnabled(boolean enabledFlag) {
        StackTraceElement[] stackTrace = Thread.currentThread().getStackTrace();
        List<String> classNameList = Arrays.stream(stackTrace).map(StackTraceElement::getClassName).collect(Collectors.toList());
        String name = classNameList.get(2);
        try {
            Class<?> clazz = Class.forName(name);
            // 判断必须是DesensitizationAutoConfiguration类调用的方法才设置开关
            boolean flag = DesensitizationAutoConfiguration.class.isAssignableFrom(clazz);
            if (flag) {
                enabled = enabledFlag;
            }
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }

    public DesensitizationSerialize() {
    }

    public DesensitizationSerialize(DesensitizationTypeEnum type, Integer startInclude, Integer endExclude) {
        this.type = type;
        this.startInclude = startInclude;
        this.endExclude = endExclude;
    }

    @Override
    public void serialize(String str, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException {
        // 判断是否开启数据脱敏
        if (enabled) {
            switch (type) {
                // 自定义类型脱敏
                case MY_RULE:
                    jsonGenerator.writeString(CharSequenceUtil.hide(str, startInclude, endExclude));
                    break;
                // userId脱敏
                case USER_ID:
                    jsonGenerator.writeString(String.valueOf(DesensitizedUtil.userId()));
                    break;
                // 中文姓名脱敏
                case CHINESE_NAME:
                    jsonGenerator.writeString(DesensitizedUtil.chineseName(String.valueOf(str)));
                    break;
                // 身份证脱敏
                case ID_CARD:
                    jsonGenerator.writeString(DesensitizedUtil.idCardNum(String.valueOf(str), 1, 2));
                    break;
                // 固定电话脱敏
                case FIXED_PHONE:
                    jsonGenerator.writeString(DesensitizedUtil.fixedPhone(String.valueOf(str)));
                    break;
                // 手机号脱敏
                case MOBILE_PHONE:
                    jsonGenerator.writeString(DesensitizedUtil.mobilePhone(String.valueOf(str)));
                    break;
                // 地址脱敏
                case ADDRESS:
                    jsonGenerator.writeString(DesensitizedUtil.address(String.valueOf(str), 8));
                    break;
                // 邮箱脱敏
                case EMAIL:
                    jsonGenerator.writeString(DesensitizedUtil.email(String.valueOf(str)));
                    break;
                // 密码脱敏
                case PASSWORD:
                    jsonGenerator.writeString(DesensitizedUtil.password(String.valueOf(str)));
                    break;
                // 中国车牌脱敏
                case CAR_LICENSE:
                    jsonGenerator.writeString(DesensitizedUtil.carLicense(String.valueOf(str)));
                    break;
                // 银行卡脱敏
                case BANK_CARD:
                    jsonGenerator.writeString(DesensitizedUtil.bankCard(String.valueOf(str)));
                    break;
                default:
            }
        } else {
            // 不做脱敏处理
            jsonGenerator.writeString(String.valueOf(str));
        }

    }

    @Override
    public JsonSerializer<?> createContextual(SerializerProvider serializerProvider, BeanProperty beanProperty) throws JsonMappingException {

        if (beanProperty != null) {
            // 判断数据类型是否为String类型
            if (Objects.equals(beanProperty.getType().getRawClass(), String.class)) {
                // 获取定义的注解
                Desensitization desensitization = beanProperty.getAnnotation(Desensitization.class);
                // 为null
                if (desensitization == null) {
                    desensitization = beanProperty.getContextAnnotation(Desensitization.class);
                }
                // 不为null
                if (desensitization != null) {
                    // 创建定义的序列化类的实例并且返回，入参为注解定义的type,开始位置，结束位置。
                    return new DesensitizationSerialize(desensitization.type(), desensitization.startInclude(),
                            desensitization.endExclude());
                }
            }

            return serializerProvider.findValueSerializer(beanProperty.getType(), beanProperty);
        }

        return serializerProvider.findNullValueSerializer(null);
    }
}
